package me.zhengjie.modules.website.service.impl;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.dysmsapi20170525.AsyncClient;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.sdk.service.dysmsapi20170525.models.SendSmsResponse;
import darabonba.core.client.ClientOverrideConfiguration;
import me.zhengjie.exception.EntityNotFoundException;
import me.zhengjie.modules.security.config.bean.LoginProperties;
import me.zhengjie.modules.security.config.bean.SecurityProperties;
import me.zhengjie.modules.security.security.TokenProvider;
import me.zhengjie.modules.security.service.OnlineUserService;
import me.zhengjie.modules.security.service.dto.JwtUserDto;
import me.zhengjie.modules.system.domain.Role;
import me.zhengjie.modules.system.domain.User;
import me.zhengjie.modules.system.service.UserService;
import me.zhengjie.modules.system.service.dto.UserDto;
import me.zhengjie.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Service
public class VerificationServiceImpl {

    @Autowired
    private UserService userService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;
    @Autowired
    private OnlineUserService onlineUserService;
    @Autowired
    private TokenProvider tokenProvider;
    @Autowired
    private SecurityProperties properties;
    @Resource
    private LoginProperties loginProperties;


    // 存储手机号对应的验证码及时间
    private static final Map<String, VerificationCode> verificationCodeCache = new ConcurrentHashMap<>();

    // 1分钟内不允许重复发送
    private static final long REPEAT_SEND_INTERVAL = TimeUnit.MINUTES.toMillis(1);
    // 验证码有效期 10分钟
    private static final long CODE_VALIDITY_PERIOD = TimeUnit.MINUTES.toMillis(10);

    public ResponseEntity<?> sendVerificationCode(String phoneNumber) {
        long currentTime = System.currentTimeMillis();

        // 检查手机号是否在1分钟内重复发送验证码
        if (verificationCodeCache.containsKey(phoneNumber)) {
            VerificationCode code = verificationCodeCache.get(phoneNumber);
            if (currentTime - code.getLastSentTime() < REPEAT_SEND_INTERVAL) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                        .body("一分钟内只能发送一次验证码");
            }
        }

        // 生成6位随机验证码
        String verificationCode = generateVerificationCode();

        try {
            // 调用阿里云短信接口发送验证码
           // sendSms(phoneNumber, verificationCode);

            // 将验证码和发送时间存储起来
            verificationCodeCache.put(phoneNumber, new VerificationCode(verificationCode, currentTime));

            // 设定验证码过期时间
            scheduleCodeExpiration(phoneNumber, currentTime);

            // 返回成功消息
            return ResponseEntity.status(HttpStatus.OK).body("验证码已发送：" + verificationCode);
        } catch (Exception e) {
            // 处理发送失败
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body("验证码发送失败，请稍后重试");
        }
    }

   /* private void sendSms(String phoneNumber, String verificationCode) throws Exception {
        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(System.getenv("o3Gw7bf1j7pn53ZG2ug4961NH2tb"))
                .accessKeySecret(System.getenv("BgXqNlBsmMScSmQhhfA3f7brFBIs"))
                .build());

        AsyncClient client = AsyncClient.builder()
                .credentialsProvider(provider)
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride("dysmsapi.ap-southeast-1.aliyuncs.com"))
                .build();

        SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                .phoneNumbers(phoneNumber)
                .signName("四川省档案馆") // 替换为您的签名
                .templateCode("SMS_476890183") // 替换为您的模板CODE
                .templateParam("{\"code\":\"" + verificationCode + "\"}")
                .build();

        CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
        SendSmsResponse resp = response.get();

        if (!"OK".equalsIgnoreCase(resp.getBody().getCode())) {
            throw new RuntimeException("短信发送失败：" + resp.getBody().getMessage());
        }

        client.close();
    }*/

    private void sendSms(String phoneNumber, String verificationCode) throws Exception {

        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId("o3Gw7bf1j7pn53ZG2ug4961NH2tb")
                .accessKeySecret("BgXqNlBsmMScSmQhhfA3f7brFBIs")
                .build());

        AsyncClient client = AsyncClient.builder()
                .credentialsProvider(provider)
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                .setEndpointOverride("dysmsapi.aliyuncs.com")
                )
                .build();

        SendSmsRequest sendSmsRequest = SendSmsRequest.builder()
                .phoneNumbers(phoneNumber)
                .signName("四川省档案馆") // 替换为您的签名
                .templateCode("SMS_476890183") // 替换为您的模板CODE
                .templateParam("{\"code\":\"" + verificationCode + "\"}")
                .build();

        CompletableFuture<SendSmsResponse> response = client.sendSms(sendSmsRequest);
        SendSmsResponse resp = response.get();

        if (!"OK".equalsIgnoreCase(resp.getBody().getCode())) {
            throw new RuntimeException("短信发送失败：" + resp.getBody().getMessage());
        }

        client.close();
    }


    private String generateVerificationCode() {
        return String.format("%06d", (int) (Math.random() * 1000000));
    }

    private void scheduleCodeExpiration(String phoneNumber, long currentTime) {
        new Thread(() -> {
            try {
                Thread.sleep(5 * 60 * 1000); // 5分钟后过期
                verificationCodeCache.remove(phoneNumber);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }

    // 验证码对象
    private static class VerificationCode {
        private final String code;
        private final long lastSentTime;

        public VerificationCode(String code, long lastSentTime) {
            this.code = code;
            this.lastSentTime = lastSentTime;
        }

        public String getCode() {
            return code;
        }

        public long getLastSentTime() {
            return lastSentTime;
        }
    }

    // 验证验证码
    public ResponseEntity<?> verifyVerificationCode(String phoneNumber, String verificationCode, HttpServletRequest request) {
        long currentTime = System.currentTimeMillis();

        // 检查手机号是否有验证码
        if (!verificationCodeCache.containsKey(phoneNumber)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("验证码不存在或已过期");
        }

        // 获取存储的验证码信息
        VerificationCode storedCode = verificationCodeCache.get(phoneNumber);

        // 验证码是否匹配
        if (!storedCode.getCode().equals(verificationCode)) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("验证码不正确");
        }

        // 验证码是否过期
        if (currentTime - storedCode.getLastSentTime() > CODE_VALIDITY_PERIOD) {
            // 删除过期的验证码
            verificationCodeCache.remove(phoneNumber);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("验证码已过期");
        }

        // 验证成功，删除验证码，确保验证码只能使用一次
        verificationCodeCache.remove(phoneNumber);
        UserDto userDto;
        try {
            // 查询用户，如果用户不存在会抛出异常
            userDto = userService.findByName(phoneNumber);
        } catch (EntityNotFoundException e) {
            // 用户不存在时，创建新用户
            User user = new User();
            user.setUsername(phoneNumber);
            user.setNickName(phoneNumber);

            Role role = new Role();
            role.setId(1L);
            user.setRoles(Collections.singleton(role));

            user.setPassword(passwordEncoder.encode("123456"));
            user.setEnabled(true);
            userService.create(user);

            // 重新查询用户
            userDto = userService.findByName(phoneNumber);
        }



        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userDto.getUsername(), "123456");
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        // 生成令牌与第三方系统获取令牌方式
        // UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());
        // Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        // SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = tokenProvider.createToken(authentication);
        final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
        // 返回 token 与 用户信息
        Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
            put("token", properties.getTokenStartWith() + token);
            put("user", jwtUserDto);
        }};
        if (loginProperties.isSingleLogin()) {
            // 踢掉之前已经登录的token
            onlineUserService.kickOutForUsername(userDto.getUsername());
        }
        // 保存在线信息
        onlineUserService.save(jwtUserDto, token, request);
        // 返回登录信息
        return ResponseEntity.ok(authInfo);


        // 返回成功消息
        //    return ResponseEntity.status(HttpStatus.OK).body("验证码验证成功");
    }

}

